/*
 * Copyright (C) 2017 Pingan, Inc. All Rights Reserved.
 */

package com.pingan.haofang.searchcloud.web.index.controller;

import com.pingan.haofang.framework.common.functional.lang.control.bean.BeanCopy;
import com.pingan.haofang.searchcloud.common.constants.WebConstants;
import com.pingan.haofang.searchcloud.common.validator.annotation.Valid;
import com.pingan.haofang.searchcloud.indexdatasource.dto.DatasourceCacheKeyDto;
import com.pingan.haofang.searchcloud.indexdatasource.dto.IndexDatasourceBuildDTO;
import com.pingan.haofang.searchcloud.indexdatasource.dto.IndexDatasourceDTO;
import com.pingan.haofang.searchcloud.indexdatasource.dto.RpcIndexDataSourceDTO;
import com.pingan.haofang.searchcloud.indexdatasource.service.IndexDatasourceService;
import com.pingan.haofang.searchcloud.quartz.service.IndexBuildScheduleTaskService;
import com.pingan.haofang.searchcloud.web.index.form.DataSourceIdForm;
import com.pingan.haofang.searchcloud.web.index.validator.IndexDatasourceValidator;
import com.pingan.haofang.searchcloud.web.index.vo.FullRpcIndexDataSourceVO;
import com.pingan.haofang.searchcloud.web.index.vo.IncCallbackRpcIndexDataSourceVO;
import com.pingan.haofang.searchcloud.web.index.vo.IndexDatasourceBuildVO;
import com.pingan.haofang.searchcloud.web.index.vo.IndexDatasourceVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
 * 索引数据源接口
 *
 * @author zhangbi617
 * @date 03/05/2017
 */
@RestController
@RequestMapping(value = WebConstants.WEB_PREFIX + "/datasource")
@Api(tags = "Index.Datasource", description = "索引数据源接口")
public class IndexDatasourceController {

    @Autowired
    private IndexDatasourceService indexDatasourceService;

    @Autowired
    private IndexBuildScheduleTaskService indexBuildScheduleTaskService;

    /**
     * 删除索引数据源
     */
    @ApiOperation("删除索引数据源")
    @DeleteMapping(value = "{datasourceId}")
    @Valid
    public void delete(
            @ApiParam(value = "数据源ID", allowableValues = "range[1,infinity]", required = true)
            @ModelAttribute DataSourceIdForm form) throws SchedulerException {
        //返回用于构建清除缓存key的dto
        DatasourceCacheKeyDto keyDto = indexDatasourceService.deleteDatasource(form.getDatasourceId());
        //清除缓存
        if (keyDto != null) {
            indexDatasourceService.datasourceCacheEvict(keyDto);
        }
        indexBuildScheduleTaskService.refresh(keyDto.getIndexId());
        indexBuildScheduleTaskService.incScheduleRefresh(keyDto.getIndexId());
    }


    /**
     * 创建索引数据源
     */
    @ApiOperation("创建索引数据源")
    @PostMapping(value = "")
    @Valid(IndexDatasourceValidator.class)
    public void createIndexDatasourceSettings(
            @RequestBody IndexDatasourceVO indexDatasource) throws SchedulerException {

        IndexDatasourceDTO indexDatasourceDTO = BeanCopy.of(indexDatasource, new IndexDatasourceDTO())
                .copy(BeanUtils::copyProperties).set(target -> target.setFullDatasourceRpc(new RpcIndexDataSourceDTO()))
                .copy((source, target) -> BeanCopy.of(source.getFullDatasourceRpc(), target.getFullDatasourceRpc())
                        .copy(BeanUtils::copyProperties).get()

                ).copy((source, target) -> target
                        .setIncDatasourceRpc(BeanCopy.ofNullable(source.getIncDatasourceRpc(), RpcIndexDataSourceDTO.class)
                                .copy(BeanUtils::copyProperties).get()))
                .get();

        indexDatasourceService.createDatasource(indexDatasourceDTO);
        indexBuildScheduleTaskService.refresh(indexDatasourceDTO.getIndexId());
        indexBuildScheduleTaskService.incScheduleRefresh(indexDatasourceDTO.getIndexId());
    }

    /**
     * 读取索引数据源列表
     */
    @ApiOperation("读取索引数据源列表")
    @GetMapping(value = "")
    @Valid(IndexDatasourceValidator.class)
    public List<IndexDatasourceVO> list(
            @ApiParam(value = "索引ID", allowableValues = "range[1,infinity]", required = true)
            @RequestParam
                    Long indexId) {

        List<IndexDatasourceDTO> indexDatasourceDTOList = indexDatasourceService.getByIndexId(indexId);
        if (CollectionUtils.isEmpty(indexDatasourceDTOList)) {
            return Collections.emptyList();
        }

        List<IndexDatasourceVO> indexDatasourceVoList = new ArrayList<IndexDatasourceVO>(indexDatasourceDTOList.size());
        for (IndexDatasourceDTO dto : indexDatasourceDTOList) {
            IndexDatasourceVO vo = transferToVO(dto);
            indexDatasourceVoList.add(vo);
        }

        return indexDatasourceVoList;
    }

    /**
     * 转换
     *
     * @param dto 数据源
     * @return
     */
    private IndexDatasourceVO transferToVO(IndexDatasourceDTO dto) {
        return BeanCopy.of(dto, new IndexDatasourceVO()).copy(BeanUtils::copyProperties)
                .set(target -> target.setFullDatasourceRpc(new FullRpcIndexDataSourceVO()))
                .copy((source, target) -> BeanUtils.copyProperties(source.getFullDatasourceRpc(),
                        target.getFullDatasourceRpc()))
                .copy((source, target) -> target.setIncDatasourceRpc(
                        BeanCopy.ofNullable(source.getIncDatasourceRpc(), IncCallbackRpcIndexDataSourceVO.class)
                                .copy(BeanUtils::copyProperties).get()))
                .get();
    }

    @ApiOperation("读取一个数据源")
    @GetMapping(value = "{id}")
    public IndexDatasourceVO get(@ApiParam(value = "数据源ID", allowableValues = "range[1,infinity]", required = true)
                                 @PathVariable Long id) {
        IndexDatasourceDTO datasourceDTO = indexDatasourceService.getById(id);
        return transferToVO(datasourceDTO);
    }

    @ApiOperation("设置数据源定时构建时机")
    @PostMapping(value = "/build/{indexId}")
    @Valid(IndexDatasourceValidator.class)
    public void saveIndexDatasourceBuild(@RequestBody IndexDatasourceBuildVO request) throws SchedulerException {
        IndexDatasourceBuildDTO dto = new IndexDatasourceBuildDTO();
        dto.setIndexId(request.getIndexId());
        dto.setCron(request.getCron());
        dto.setIncCron(request.getIncCron());
        indexDatasourceService.updateDatasourceBuild(dto);
    }

    @ApiOperation("获取数据源定时构建时机")
    @GetMapping(value = "/build/{indexId}")
    public IndexDatasourceBuildVO getIndexDatasourceBuild(@ApiParam(value = "索引ID", allowableValues = "range[1,infinity]", required = true)
                                                          @PathVariable Long indexId) {
        IndexDatasourceBuildDTO dto = indexDatasourceService.getDatasourceBuild(indexId);

        IndexDatasourceBuildVO response = new IndexDatasourceBuildVO();
        response.setIndexId(indexId);

        if (dto != null) {
            response.setCron(dto.getCron());
            response.setId(dto.getId());
            response.setIncCron(dto.getIncCron());
        }
        return response;

    }
}
